package cn.com.lyb.job.service.impl;

import cn.com.lyb.annotation.RedissionLock;
import cn.com.lyb.asyncTask.construnctor.AsyncTaskConstructor;
import cn.com.lyb.asyncTask.manage.AsyncTaskManager;
import cn.com.lyb.core.constant.Constants;
import cn.com.lyb.core.exception.BizException;
import cn.com.lyb.core.exception.BizExceptionEnum;
import cn.com.lyb.enums.JobStatusEnum;
import cn.com.lyb.job.dao.JobDao;
import cn.com.lyb.job.entity.JobDO;
import cn.com.lyb.job.entity.JobInstanceDO;
import cn.com.lyb.job.service.IJobInstanceService;
import cn.com.lyb.job.service.IJobService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 任务表 服务实现类
 * </p>
 *
 * @author lvyuanbo
 * @since 2024-07-11
 */
@Service
public class JobServiceImpl extends ServiceImpl<JobDao, JobDO> implements IJobService {

    @Autowired
    private JobDao jobDao;

    @Autowired
    private IJobInstanceService jobInstanceService;

    @Autowired
    private AsyncTaskManager asyncTaskManager;

    /**
     * 新增任务job
     *
     * @param name
     * @param type
     * @param command
     * @return
     */
    @Override
    public void createEntity(String name, String type, String command) {
        LambdaQueryWrapper<JobDO> wrapper = new LambdaQueryWrapper<JobDO>();
        wrapper.eq(JobDO::getName, name);
        wrapper.eq(JobDO::getDel, Constants.IS_NOT_DEL);
        wrapper.ne(false, JobDO::getId, null);
        JobDO jobDO = jobDao.selectOne(wrapper);
        if(!Objects.isNull(jobDO)){
           throw new BizException(BizExceptionEnum.JOB_NAME_REPEAT);
        }
        JobDO job = new JobDO();
        job.setName(name);
        job.setType(type);
        job.setCommand(command);
        job.setDel(Constants.IS_NOT_DEL);
        job.setCreateTime(new Date());
        jobDao.insert(job);
    }

    /**
     * 修改任务job
     *
     * @param id
     * @param name
     * @param command
     */
    @Override
    @RedissionLock(keyPrefix = "#id", type = "job")
    public void updateEntity(Long id, String name, String command) {
        LambdaQueryWrapper<JobDO> wrapper = new LambdaQueryWrapper<JobDO>();
        wrapper.eq(JobDO::getName, name);
        wrapper.eq(JobDO::getDel, Constants.IS_NOT_DEL);
        wrapper.ne(true, JobDO::getId, id);
        JobDO jobDO = jobDao.selectOne(wrapper);
        if(!Objects.isNull(jobDO)){
            throw new BizException(BizExceptionEnum.JOB_NAME_REPEAT);
        }
        JobDO jobDO1 = jobDao.selectById(id);
        jobDO1.setName(name);
        jobDO1.setCommand(command);
        jobDO1.setUpdateTime(new Date());
        jobDao.updateById(jobDO1);
    }

    /**
     * 删除任务job
     *
     * @param ids
     */
    @Override
    public void deleteEntity(String ids) {
        List<String> list = Arrays.asList(ids.split(","));
        List<Long> idList = list.stream().map(Long::valueOf).collect(Collectors.toList());
        jobDao.deleteEntityByIdList(idList);
    }

    /**
     * 查询列表
     *
     * @param searchVal
     * @param start
     * @param length
     * @return
     */
    @Override
    public List<JobDO> selectPage(String searchVal, Integer start, Integer length) {
        PageHelper.startPage(start, length);
       return jobDao.selectPageByName(searchVal);
    }

    /**
     * 运行任务
     *
     * @param id
     */
    @Override
    public void runTask(Long id) {
        JobInstanceDO jobInstanceDO = jobInstanceService.checkRunByJobId(id);
        if(jobInstanceDO != null && (jobInstanceDO.getStatus().equals("1") || jobInstanceDO.getStatus().equals("2"))){
            throw new BizException(BizExceptionEnum.JOB_STATUS_RUNNING);
        }
        JobInstanceDO jobInstanceDO1 = new JobInstanceDO();
        jobInstanceDO1.setJobId(id);
        jobInstanceDO1.setStatus(JobStatusEnum.NOT_STARTED.getCode());
        jobInstanceDO1.setStartTime(new Date());
        jobInstanceService.save(jobInstanceDO1);
        AsyncJobRunConstructor runTask = new AsyncJobRunConstructor(jobInstanceDO1.getId(), jobInstanceService);
        asyncTaskManager.submit(runTask);
    }
}

class AsyncJobRunConstructor implements AsyncTaskConstructor{

    private Long id;

    private IJobInstanceService jobInstanceService;

    public AsyncJobRunConstructor(Long id, IJobInstanceService jobInstanceService) {
        this.id = id;
        this.jobInstanceService = jobInstanceService;
    }

    /**
     * 异步执行方法
     */
    @Override
    public void async() {
        // 模拟运行任务
        Random random = new Random();
        int sleepTime = random.nextInt(10) + 1;
        try {
            Thread.sleep(sleepTime * 1000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        JobInstanceDO byId = jobInstanceService.getById(id);
        byId.setEndTime(new Date());
        byId.setStatus(JobStatusEnum.SUCCESS.getCode());
        jobInstanceService.updateById(byId);
    }

    /**
     * 成功回调方法
     */
    @Override
    public void callBackAfterSuccess() {

    }

    /**
     * 失败回调方法
     *
     * @param throwable
     */
    @Override
    public void callBackAfterFail(Throwable throwable) {

    }
}
